#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
sys.path.append('/usr/lib/python%s/site-packages/oldxml' % sys.version[:3])
import PodcastTaggerUtils
import time
import threading
import logging
import os
import sys
import eyeD3
from PodcastTagger_ui import Ui_PodTagger
from PyQt4 import QtCore, QtGui

PodcastTaggerUtils.ptlogger.setLevel(logging.INFO)

class PodcastTaggerApp(QtGui.QMainWindow):
    def __init__(self,parent=None):
        QtGui.QMainWindow.__init__(self,parent)
        self.PodcastFeeds = []
        self.changes = {}
        self.ui = Ui_PodTagger()
        self.initUI()
	self.nThreads = 7
        self.PodcastInfo = PodcastTaggerUtils.readPodcastFile(PodcastTaggerUtils.podcast_file)
        for k,v in self.PodcastInfo.iteritems():
            newItem = QtGui.QTreeWidgetItem(QtCore.QStringList(QtCore.QString(k.split('/')[-1])))
            newItem.setFlags(QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsUserCheckable
                            | QtCore.Qt.ItemIsEnabled))
            newItem.setCheckState(0,QtCore.Qt.Checked)
            self.ui.treePodcasts.addTopLevelItem(newItem)
        self.ui.treePodcasts.sortItems(0,QtCore.Qt.AscendingOrder)

    def initUI(self):
        self.ui.setupUi(self)
        self.ui.btnApplyChanges.setEnabled(False)
        self.ui.treePodcasts.setHeaderLabel(QtCore.QString('Podcasts'))
        self.ui.treeChanges.setHeaderLabel(QtCore.QString('Changes'))
        self.ui.treePodcasts.setSortingEnabled(True)
        self.ui.treeChanges.setSortingEnabled(True)
        self.hideProgressBar()
        self.connectSlots()


    def connectSlots(self):
        QtCore.QObject.connect(self.ui.btnCheckPodcasts,QtCore.SIGNAL("clicked()"),
                                self.checkPodcasts)
        QtCore.QObject.connect(self.ui.btnApplyChanges,QtCore.SIGNAL("clicked()"),
                                self.applyChanges)
        QtCore.QObject.connect(self.ui.btnCheckAll,QtCore.SIGNAL("clicked()"),
                                self.checkAllItems)
        QtCore.QObject.connect(self.ui.btnUncheckAll,QtCore.SIGNAL("clicked()"),
                                self.uncheckAllItems)
        QtCore.QObject.connect(self.ui.treePodcasts,QtCore.SIGNAL("itemClicked(QTreeWidgetItem *,int)"),
                                self.checkEnabledPodcasts)

    def showProgressBar(self,label):
        self.ui.progressBar.show()
        self.ui.lblProgress.show()
        self.ui.lblProgress.setText(QtCore.QString(label))
        app.processEvents()

    def hideProgressBar(self):
        self.ui.lblProgress.setText(QtCore.QString(''))
        self.ui.progressBar.hide()
        self.ui.lblProgress.hide()
        app.processEvents()

    def enableButtons(self):
        self.ui.btnCheckPodcasts.setEnabled(True)
        self.ui.btnCheckAll.setEnabled(True)
        self.ui.btnUncheckAll.setEnabled(True)
        self.ui.btnApplyChanges.setEnabled(len(self.changes) > 0)
        app.processEvents()

    def enableTrees(self):
        self.ui.treePodcasts.setEnabled(True)
        self.ui.treeChanges.setEnabled(True)
        app.processEvents()

    def disableButtons(self):
        self.ui.btnCheckPodcasts.setEnabled(False)
        self.ui.btnApplyChanges.setEnabled(False)
        self.ui.btnCheckAll.setEnabled(False)
        self.ui.btnUncheckAll.setEnabled(False)
        app.processEvents()

    def disableTrees(self):
        self.ui.treePodcasts.setEnabled(False)
        self.ui.treeChanges.setEnabled(False)
        app.processEvents()

    def checkAllItems(self):
        for item in self.ui.treePodcasts.findItems(QtCore.QString('*'),QtCore.Qt.MatchWildcard):
            item.setCheckState(0,QtCore.Qt.Checked)

    def uncheckAllItems(self):
        for item in self.ui.treePodcasts.findItems(QtCore.QString('*'),QtCore.Qt.MatchWildcard):
            item.setCheckState(0,QtCore.Qt.Unchecked)

    def checkEnabledPodcasts(self):
        app.processEvents()
        for p in self.PodcastFeeds:
            podcast = p[1]
            item_list = self.ui.treePodcasts.findItems(QtCore.QString(podcast.title),
                        QtCore.Qt.MatchFlags(QtCore.Qt.MatchExactly))
            if item_list != None and len(item_list) == 1:
                p[0] =  bool(item_list[0].checkState(0) == QtCore.Qt.Checked)

    def checkPodcasts(self):
        self.fillPodcastList()
        self.getChanges()

    def fillPodcastList(self):
        self.showProgressBar('Downloading Podcast Feeds')
	self.setWindowTitle('Downloading')
        self.disableButtons()
        self.disableTrees()
        self.PodcastFeeds = []
        PodcastTaggerUtils.ptlogger.info('Getting Podcasts List')
        podcast_info = self.PodcastInfo
        n = len(podcast_info)
        PodcastTaggerUtils.ptlogger.debug('%d Podcasts to load',n)
        threads = []
        i = 0
        for i in range(self.nThreads):
            p = podcast_info.popitem()
            threads.append(threading.Thread(target=getPodcastThread,args=(p[0],p[1])))
            threads[-1].start()
            alive = True
        while alive:
            alive = False
            for t in range(len(threads)):
                if threads[t] != None and threads[t].isAlive():
                    alive = True
                else:
                    del threads[t]
                    if len(podcast_info) > 0:
                        i = i + 1
                        p = podcast_info.popitem()
                        threads.append(threading.Thread(target=getPodcastThread,args=(p[0],p[1])))
                        threads[-1].start()
                        alive = True
                    else:
                        threads.append(None)
            app.processEvents()
	    p = int(round(100 * float(i) / float(n)))
            self.ui.progressBar.setValue(p)
	    self.setWindowTitle('Downloading - ' + str(p) + '%')
        PodcastTaggerUtils.ptlogger.info('Got All Feeds')
        self.enableButtons()
        self.enableTrees()
	self.setWindowTitle('PodcastTagger')
        self.hideProgressBar()

    def getChanges(self):
        self.showProgressBar('Looking for Changes')
	self.setWindowTitle('Checking')
        self.ui.progressBar.setValue(0)
        self.disableButtons()
        self.disableTrees()
	getChangesThread()
        #t = threading.Thread(target=getChangesThread)
        #t.start()
        #while t.isAlive():
            #app.processEvents()
            #time.sleep(0.1)

        self.ui.treeChanges.clear()
        for pt,pi in self.changes.iteritems():
            newItem = QtGui.QTreeWidgetItem(QtCore.QStringList(QtCore.QString(pt)))
            newFileItem = None
            for f,c in pi.iteritems():
                newFileItem = QtGui.QTreeWidgetItem(QtCore.QStringList(QtCore.QString(f.split('/')[-1])))
                newTagItem = None
                for ct,cv in c.iteritems():
                    newFileItem.addChild(QtGui.QTreeWidgetItem(QtCore.QStringList(QtCore.QString(ct + ': ' + cv))))
                if newFileItem != None:
                    newItem.addChild(newFileItem)
            if newItem != None and newItem.childCount() > 0:
                newItem.setFlags(QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsUserCheckable
                                | QtCore.Qt.ItemIsEnabled))
                newItem.setCheckState(0,QtCore.Qt.Checked)
                self.ui.treeChanges.addTopLevelItem(newItem)
                self.ui.treeChanges.sortItems(0,QtCore.Qt.AscendingOrder)

	self.setWindowTitle('PodcastTagger')
        self.enableButtons()
        self.enableTrees()
        self.hideProgressBar()

    def applyChanges(self):
        self.showProgressBar('Applying Changes')
	self.setWindowTitle('Applying')
        self.ui.progressBar.setValue(0)
        i = 0
        for p,c in self.changes.iteritems():
            PodcastTaggerUtils.ptlogger.debug('Applying changes to podcast \"%s\"\n',p)
            for filename,tags in c.iteritems():
                PodcastTaggerUtils.ptlogger.debug('File Name: \"%s\"\n',filename)
                PodcastTaggerUtils.ApplyChange([filename,tags])
                app.processEvents()
            i = i + 1
	    p = int(round(100 * float(i) / float(len(self.changes.keys()))))
            self.ui.progressBar.setValue(p)
	    self.setWindowTitle('Applying - ' + str(p) + '%')
            app.processEvents()
        PodcastTaggerUtils.ptlogger.debug('All Podcast Tags Updated')
	self.setWindowTitle('PodcastTagger')
        self.changes = {}
        self.ui.btnApplyChanges.setEnabled(False)
        self.ui.treeChanges.clear()
        self.hideProgressBar()
        self.PodcastFeeds = []
        self.changes = {}

def getPodcastThread(path,info):
    if path != None and info != None:
        podcast = PodcastTaggerUtils.GetPodcastFeed(path,info)
        if podcast != None:
            pt_app.PodcastFeeds.append([True,podcast])
            treeItems = pt_app.ui.treePodcasts.findItems(QtCore.QString(path.split('/')[-1]),QtCore.Qt.MatchExactly,0)
            if len(treeItems) == 1:
                treeItem = treeItems[0]
                for item in podcast.items:
                    treeItem.addChild(QtGui.QTreeWidgetItem(QtCore.QStringList(QtCore.QString(item[1]))))
                    app.processEvents()

def getChangesThread():
    tag = eyeD3.Tag()
    pt_app.changes = {}
    CustomTags = PodcastTaggerUtils.readPodcastFile(PodcastTaggerUtils.podcast_file)
    n = 0
    i = 0
    for p in pt_app.PodcastFeeds:
        if p[0]:
            n = n + len(p[1].items)
    for p in pt_app.PodcastFeeds:
        # First check to see if this podcast is enabled (i.e., if it is one we want
        # to look at).
        if p[0]:
            podcast = p[1]
            PodcastTaggerUtils.ptlogger.debug('Checking changes in podcast \"%s\"',podcast.title)
            ct = None
            if CustomTags.has_key(podcast.path):
                ct = CustomTags[podcast.path]
                if ct.has_key('album'):
                    podcast.title = ct['album']
                if ct.has_key('author'):
                    podcast.author = ct['author']
            if ct != None and podcast != None:
                pt_app.changes[podcast.title] = {}
            for item in podcast.items:
                if eyeD3.isMp3File(item[0]):
                    if ct != None and ct.has_key('title'):
                        # Set the custom title tag
                        tm = ct['title']
                        tm = tm.replace('%{pubDate}',item[2])
                        tm = tm.replace('%{title}',item[1])
                        item[1] = tm
                    try:
                        # Link to the mp3 file and pull ID3 Tag info off of it
                        tag.link(item[0])
                        title = tag.getTitle()
                        album = tag.getAlbum()
                        author = tag.getArtist()
                        if tag.getGenre() == None:
                            genre = ''
                        else:
                            genre = tag.getGenre().getName()
                    except eyeD3.tag.TagException:
                        PodcastTaggerUtils.ptlogger.error('Tag Exception on file \"%s\"',item[0])
                        continue
                    except eyeD3.tag.GenreException:
                        genre = ''
                    d = {}
                    try:
                        PodcastTaggerUtils.ptlogger.debug('album = %s; podcast.title = %s',album,podcast.title)
                        if album != podcast.title and podcast.title != "":
                            d['album'] = podcast.title
                        PodcastTaggerUtils.ptlogger.debug('title = %s; item[1] = %s',title,item[1])
                        if title != str(unicode(item[1])) and str(unicode(item[1])) != "":
                            d['title'] = item[1]
                        PodcastTaggerUtils.ptlogger.debug('author = %s; podcast.author = %s',author,podcast.author)
                        if author != podcast.author and podcast.author != '':
                            d['author'] = podcast.author
                        PodcastTaggerUtils.ptlogger.debug('genre = %s',genre)
                        if genre != 'Podcast':
                            d['genre'] = 'Podcast'
                        if d != {}:
                            if not(pt_app.changes.has_key(podcast.title)):
                                pt_app.changes[podcast.title] = {}
                            pt_app.changes[podcast.title][item[0]] = d
                    except UnicodeEncodeError:
                        PodcastTaggerUtils.ptlogger.error('Unicode Encode Error on file \"%s\"',item[0])
                        continue
                    if pt_app.changes.has_key(podcast.title) and pt_app.changes[podcast.title] == {}:
                        pt_app.changes.pop(podcast.title)
                    i = i + 1
		    p = int(round(100 * float(i) / float(n)))
		    pt_app.setWindowTitle('Checking - ' + str(p) + '%')
                    pt_app.ui.progressBar.setValue(p)

app = QtGui.QApplication(sys.argv)
pt_app = PodcastTaggerApp()
pt_app.show()
sys.exit(app.exec_())
